package dsx.rpcProxy;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;

import dsx.config.Config;
import dsx.config.ConfigItem;
import dsx.console.DsxConsole;
import dsx.inf.IConverter;
import dsx.inf.INetProxy;
import dsx.inf.ISlicer;
import dsx.log.ServLog;
import dsx.system.ThreadEx;

public class UdpProxy implements INetProxy {

	String netProxyName;
	ISlicer slicer;
	IConverter converter;

	ArrayList<_UdpConfig> configLst = null;
	int maxConnNum = 10;

	int connNum = 0;
	int workingNum = 0;

	int status = 0; // 状态：0 关闭，1 启动，2 正在关闭

	Queue<UdpClient> clientQueue = new LinkedList<UdpClient>();

	private UdpClient getClient() {
		synchronized (clientQueue) {
			try {
				if (status != 1)
					return null;
				if (clientQueue.size() > 0) {
					workingNum++;
					return clientQueue.poll();
				} else {
					if (connNum < maxConnNum && configLst != null) {
						UdpClient client = new UdpClient();

						client.start(this.configLst, this.slicer,
								this.converter);
						connNum++;
						workingNum++;
						return client;
					} else {
						return null;
					}
				}
			} catch (Exception ex) {
				return null;
			}
		}
	}

	private void returnClient(UdpClient tcpClient) {
		synchronized (clientQueue) {
			workingNum--;
			switch (status) {
			case 1:
				clientQueue.add(tcpClient);
				break;
			case 2:
				tcpClient.stop();
				if (workingNum == 0) {
					status = 0;
					for (UdpClient client : clientQueue)
						client.stop();
					clientQueue.clear();
				}
				break;
			// 不会出现 status == 0 时调用returnClient的情况
			}
		}
	}

	@Override
	public boolean start(String netProxyName, ISlicer slicer,
			IConverter converter) {
		while (status == 2)
			ThreadEx.sleepEx(100);
		synchronized (clientQueue) {
			if (status == 1)
				return false;
			this.netProxyName = netProxyName;
			this.slicer = slicer;
			this.converter = converter;
			connNum = 0;
			workingNum = 0;
			loadConfig();
			status = 1;
			return true;
		}
	}

	@Override
	public void stop() {
		synchronized (clientQueue) {
			if (workingNum == 0) {
				for (UdpClient client : clientQueue) {
					client.stop();
				}
				clientQueue.clear();
				status = 0;
			} else {
				status = 2;
			}
		}
	}

	@Override
	public void restart() {
		stop();
		start(this.netProxyName, this.slicer, this.converter);
	}

	@Override
	public Object request(Object reqObj, Class<?> answType) {
		UdpClient client = getClient();
		if (client == null)
			return null;
		try {
			return client.request(reqObj, answType);
		} finally {
			returnClient(client);
		}
	}

	@Override
	public Object request(Object reqObj, Class<?> answType, String host,
			int port) {
		UdpClient client = getClient();
		if (client == null)
			return null;
		try {
			return client.request(reqObj, answType, host, port);
		} finally {
			returnClient(client);
		}
	}

	// 加载服务配置
	private void loadConfig() {
		try {
			ArrayList<ArrayList<ConfigItem>> sections = Config
					.getSections(netProxyName);
			configLst = new ArrayList<_UdpConfig>();
			for (int i = 0; i < sections.size(); i++) {
				ArrayList<ConfigItem> fields = sections.get(i);
				_UdpConfig config = new _UdpConfig();
				for (int j = 0; j < fields.size(); j++) {
					ConfigItem field = fields.get(j);
					switch (field.name) {
					case "maxConnNum":
						maxConnNum = Integer.parseInt(field.value);
						break;
					case "ip":
						config.setIp(field.value);
						break;
					case "port":
						config.setPort(Integer.parseInt(field.value));
						break;
					case "timeout":
						config.setTimeout(Integer.parseInt(field.value));
						break;
					}
				}
				configLst.add(config);
			}
		} catch (Exception ex) {
			configLst = null;
			DsxConsole.out(ex.getMessage(), "rpcProxy", ServLog.error);
		}
	}

}
